import random
import uuid
from datetime import timedelta, datetime

from fastapi import Depends
from fastapi import Request, Form
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from typing import Dict, Optional, Union
from jose import JWTError, jwt
from loguru import logger
from pydantic import BaseModel
from sqlalchemy.orm import Session

from apis_module.jsonvo.login_vo import UserLogin
from apis_module.dao.user_dao import get_user_info
from apis_module.model.users_model import Users
from config.env import JwtConfig
from utils.pwd_util import PwdUtil
from utils.response_util import LoginException

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="login/loginByAccount")


class CustomOAuth2PasswordRequestForm(OAuth2PasswordRequestForm):
    """
    自定义OAuth2PasswordRequestForm类，增加验证码及会话编号参数
    """

    def __init__(
            self,
            username: str,
            password: str,
    ):
        super().__init__(username=username, password=password)
        print(username)


class AuthLoginModel(BaseModel):
    username: str
    password: str


async def authenticate_user(request: Request, query_db: Session, login_user: UserLogin):
    user: Users = await get_user_info(login_user.student_no, query_db)
    if not user:
        logger.warning("User not found")
        raise LoginException(data="", message="用户不存在")
    if not PwdUtil.verify_password(login_user.password, user.password):
        logger.warning("wrong password")
        raise LoginException(data="", message="密码错误")

    return user


def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None):
    """
        根据登录信息创建当前用户token
        :param data: 登录信息
        :param expires_delta: token有效期
        :return: token
    """
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(minutes=15)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, JwtConfig.SECRET_KEY, algorithm=JwtConfig.ALGORITHM)
    return encoded_jwt
